package com.star.robot.wxpay;

import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.star.robot.entity.JiaoFei;
import com.star.robot.repository.JiaoFeiRepository;
import com.star.robot.repository.TeamRepository;
import io.swagger.annotations.ApiOperation;
import jdk.nashorn.internal.runtime.regexp.joni.Config;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.util.*;

/**
 * Created by mawenlong on 2019/6/8.
 */
@Controller
@RequestMapping("/wechat")
@Slf4j
public class WechatController {
    @Autowired
    private WxMpService wxMpService;
    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private TeamRepository teamRepository;
    @Autowired
    private JiaoFeiRepository jiaoFeiRepository;
    @Value("${wx.pay.server}")
    private String WX_PAY_SERVER;
    @GetMapping("/authorize")
    public String authorize(){
        String url = WX_PAY_SERVER+"/wechat/userInfo";
        String returnUrl = WX_PAY_SERVER+"/wechat/order";
        String redirectURL = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, URLEncoder.encode(returnUrl));
        log.info("【微信网页授权】获取code,redirectURL={}", redirectURL);
        return "redirect:" + redirectURL;
    }
    @GetMapping("/userInfo")
    public String userInfo(@RequestParam("code") String code,
                           @RequestParam("state") String returnUrl,
                           HttpServletRequest request) throws Exception {
        log.info("【微信网页授权】code={}", code);
        log.info("【微信网页授权】state={}", returnUrl);
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken;
        try {
            wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
        } catch (WxErrorException e) {
            log.info("【微信网页授权】{}", e);
            throw new Exception(e.getError().getErrorMsg());
        }
        String openId = wxMpOAuth2AccessToken.getOpenId();
        request.getSession().setAttribute("open_id",openId);
        log.info("【微信网页授权】openId={}", openId);
        return "redirect:/front/login.html";
    }

    @GetMapping("/order")
    @ResponseBody
    public Map<String,Object> unifiedOrder(String teamIds, HttpServletRequest request) throws Exception {
        String tradeNo = System.currentTimeMillis()+"";
        int sum=0;
        String[] teamId = teamIds.split(",");
        for(int i=0;i<teamId.length;i++ ){
            int count = teamRepository.getMemberCount(teamId[i]);
            JiaoFei jiaoFei = new JiaoFei();
            jiaoFei.setCreateTime(new Date());
            jiaoFei.setStatus(false);
            jiaoFei.setValue((float)count*100);
            jiaoFei.setTeam(teamRepository.findLongById(Long.parseLong(teamId[i])));
            jiaoFei.setTradeNo(tradeNo);
            jiaoFeiRepository.save(jiaoFei);
            sum = sum + count*100*100;
        }
        String ip = getIpAddr(request);
        String openId = (String) request.getSession().getAttribute("open_id");
        //支付参数
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
        wxPayUnifiedOrderRequest.setBody("河南青少年机器人竞赛");
        wxPayUnifiedOrderRequest.setOutTradeNo(tradeNo);
        wxPayUnifiedOrderRequest.setTotalFee(sum/(100*100));
        wxPayUnifiedOrderRequest.setSpbillCreateIp(ip);
        wxPayUnifiedOrderRequest.setOpenid(openId);
        wxPayUnifiedOrderRequest.setNotifyURL(WX_PAY_SERVER+"/wechat/notify/order");
        wxPayUnifiedOrderRequest.setTradeType("JSAPI");
        try
        {
            WxPayMpOrderResult wxPayMpOrderResult= wxPayService.createOrder(wxPayUnifiedOrderRequest);
            jiaoFeiRepository.savePrepayId(wxPayMpOrderResult.getPackageValue().split("=")[1],tradeNo);
            Map<String,Object> map = new HashMap<String,Object>();
            WxJsapiSignature wxJsapiSignature = wxMpService.createJsapiSignature(WX_PAY_SERVER+"/front/payConfirm.html");
            map.put("signature",wxJsapiSignature);
            map.put("payInfo",wxPayMpOrderResult);
            return map;

        } catch (WxPayException e)
        {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @ApiOperation(value = "支付回调通知处理")
    @PostMapping("/notify/order")
    public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
        final WxPayOrderNotifyResult notifyResult = this.wxPayService.parseOrderNotifyResult(xmlData);
        // TODO 根据自己业务场景需要构造返回对象
        if("success".equalsIgnoreCase(notifyResult.getReturnCode())){
            int count = jiaoFeiRepository.updateStatus(notifyResult.getOutTradeNo());
            if(count>0){
                return WxPayNotifyResponse.success("成功");
            }
        }
        return WxPayNotifyResponse.fail("失败");
    }
    /**
     * 获取用户真实IP地址，不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址,
     * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值
     *
     * @return ip
     */
    private String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        System.out.println("x-forwarded-for ip: " + ip);
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if( ip.indexOf(",")!=-1 ){
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            System.out.println("Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
            System.out.println("WL-Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
            System.out.println("HTTP_CLIENT_IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            System.out.println("HTTP_X_FORWARDED_FOR ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
            System.out.println("X-Real-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            System.out.println("getRemoteAddr ip: " + ip);
        }
        System.out.println("获取客户端ip: " + ip);
        return ip;
    }
}